import { type RouteRecordRaw } from "vue-router"
import { type Menu } from "@/api/system-api/menu/types/menu"
import { defineStore } from "pinia"
import { computed, ref } from "vue"
import { getUserMenu } from "@/api/system-api/menu/index"
import { constantRoutes } from "@/router"
import store from ".."
import { generateTree, TreeResult } from "@/utils/tree"
export const useMenuStore = defineStore("menu", () => {
  //真正的路由对象
  const routes = ref<RouteRecordRaw[]>([])
  const menu = ref<Menu[]>([])
  const routeTree = ref<RouteRecordRaw[]>([])
  let treeMap = {} as Map<any, RouteRecordRaw>
  const getMenu = async () => {
    await getUserMenu().then((res) => {
      if (res.code === 2000) {
        const m = res.items
        menu.value = m
        const { tree, map } = getMenuTree(res.items)
        routeTree.value = tree
        treeMap = map
        //routes.value=constantRoutes.concat(routeTree.value)
        routes.value = constantRoutes.concat(getRoutes())
        routeTree.value = constantRoutes.concat(routeTree.value)
      }
    })
  }
  const buttons = computed(() => menu.value.filter((t) => t.menuType === "button"))
  const Layouts = () => import("@/layouts/index.vue")
  const modules = import.meta.glob("../../views/**/*.vue")
  /**
   * 根据后台数据直接生成菜单树(菜单渲染用这个数据)
   * @param source 后台数据
   * @returns 菜单树
   */
  function getMenuTree(source: Menu[]): TreeResult<RouteRecordRaw> {
    const menuTree = generateTree<Menu, RouteRecordRaw>(
      source,
      (t) => (t.menuParentId === 0 || t.menuParentId == null) && t.isUse === 1 && t.isHidden != 1,
      (pnode, cnode) => pnode.meta?.id === cnode.menuParentId,
      (t) => t.children,
      (t) => menu2Route(t),
      (t) => t.meta?.id
    )
    return menuTree
  }
  // function getRoute(source: Menu[]): RouteRecordRaw[] {
  //   const route = generateTree<Menu, RouteRecordRaw>(
  //     source,
  //     (t) =>
  //       (t.menuParentId === 0 || t.menuParentId == null) && t.isUse === 1 && t.isHidden != 1 && t.menuType != "button",
  //     (pnode, cnode) =>
  //       pnode.meta?.id === cnode.menuParentId && cnode.isUse === 1 && cnode.isHidden != 1 && cnode.menuType != "button",
  //     (t) => t.children,
  //     (t) => menu2Route(t)
  //   )
  //   return route.tree
  // }
  /**
   * 获取菜单是几级菜单
   * @param id 当前菜单id
   * @returns 菜单级别
   */
  function getMenuLevel(id: number): number {
    let lev = 0
    let cur = treeMap.get(id)
    while (cur != null && cur != undefined) {
      cur = treeMap.get(cur.meta?.parentId)
      lev++
    }
    return lev
  }
  // function createDynamicRoute(source: Menu[]): RouteRecordRaw[] {
  //   const routes = [] as RouteRecordRaw[]
  //   source
  //     .filter(
  //       (t) =>
  //         (t.menuParentId === 0 || t.menuParentId == null) && t.isUse === 1 && t.isHidden != 1 && t.menuType != "button"
  //     )
  //     .forEach((t) => {
  //       const route = menu2Route(t)
  //       createDynamicChildrenRoute(route, source)
  //       routes.push(route)
  //     })
  //   return routes
  // }
  // function createDynamicChildrenRoute(parent: RouteRecordRaw, source: Menu[]): void {
  //   source
  //     .filter((t) => t.menuParentId === parent.meta?.id && t.isUse === 1 && t.isHidden != 1 && t.menuType != "button")
  //     .forEach((t) => {
  //       const route = menu2Route(t)
  //       createDynamicChildrenRoute(route, source)
  //       parent.children?.push(route)
  //     })
  // }
  /**
   * 根据后台的路由数据生成真实的路由
   * 如果1级路由是目录，按正常逻辑处理
   * 如果1级路由是菜单，需要对路由进行升级
   * 如果菜单路由大等级大于2，需要对路由进行升级
   * @returns 真正的路由
   */
  function getRoutes(): RouteRecordRaw[] {
    //这个对象用于存储每一个路由对象 便于查找
    const routeMap = new Map<Number, RouteRecordRaw>()
    //这个对象作为返回结果
    const routes = [] as RouteRecordRaw[]
    //这个对象用作缓存，部分二级路由生成时1级路由还未生成，放到此处缓存
    const earlierRoutes = [] as RouteRecordRaw[]
    //降级路由 所有路由等级超过2的菜单全部放到这个里面
    const downgradeRoute: RouteRecordRaw = {
      path: "/downgradeRoute",
      name: "downgradeRoute",
      redirect: "/",
      component: Layouts,
      meta: {
        id: 9999,
        title: "降级路由",
        type: "directory"
      },
      children: []
    }
    routes.push(downgradeRoute)
    treeMap.forEach((value) => {
      if (value.meta?.menuType != "button") {
        const route = Object.assign({}, value)
        //children全部置空
        route.children = []
        routeMap.set(value.meta!.id!, route)
        const lv = getMenuLevel(value.meta!.id!)
        if (route.meta?.type === "menu") {
          route.meta.buttonKeys = value.children?.filter((t) => t.meta?.type === "button").map((t) => t.meta!.key!)
        }
        if (lv === 1) {
          //1级路由是菜单的直接放到路由表中
          if (route.meta?.type === "directory") {
            routes.push(route)
          } else {
            //对路由进行升级 把他放到降级路由下就变成二级路由了
            downgradeRoute.children.push(route)
          }
        } else if (lv === 2) {
          //二级路由放到一级路由下
          const p = routeMap.get(value.meta!.parentId!)
          if (p === null || p === undefined) {
            earlierRoutes.push(route)
          } else {
            p.children?.push(route)
          }
        } else {
          //三级路由放到降级路由下面
          downgradeRoute.children.push(route)
        }
      }
    })
    earlierRoutes.forEach((t) => {
      const parentId = treeMap.get(t.meta?.id)?.meta?.parentId
      const p = routeMap.get(parentId!)
      p?.children?.push(t)
    })
    return routes
  }
  /**
   * 后台menu实体转为真正的路由对象
   * @param source 后台menuList
   * @returns
   */
  function menu2Route(source: Menu): RouteRecordRaw {
    const route = {} as RouteRecordRaw
    route.path = source.menuRoute
    route.name = source.menuName
    route.redirect = source.menuRedirect
    if (source.menuType === "directory") {
      route.component = Layouts
    } else {
      route.component = modules[`../..${source.menuPath}.vue`]
    }
    route.meta = {
      id: source.id,
      key: source.menuKey,
      parentId: source.menuParentId,
      title: source.menuName,
      elIcon: source.menuIcon,
      hidden: source.isHidden === 1,
      keepAlive: source.isCache === 1,
      type: source.menuType
    }
    route.children = []
    return route
  }
  return { routes, menu, routeTree, buttons, getMenu }
})
export function useMenuStoreHook() {
  return useMenuStore(store)
}

// function getMenuLevel(menu:Menu):number{

// }
